Android Library 和 IDs 的爱恨情仇
版权声明:
本公众号发布的所有文章,均属于原创,版权归本公众号所有。
未经允许,不得转载。
一、前言
因为业务需要,需要把手上一个项目,按模块拆分出来,进行模块化处理,来适应不同的版本需求。大致的流程就是按模块化的思想,将各个业务进行拆分,总之就是一堆解耦的操作。模块化的好处有很多,这里就不一一说明了。
确定好需要拆分的模块之后,其实具体业务代码都是现成的,只是需要制定好接口,然后”有技巧”的复制现有代码到各个该在的模块内就可以了。在这个过程中,碰到一些问题,在一些原有代码中,使用 switch-case 操作一些 IDs 的资源的时候,原本是没有问题的,但是当它被复制到 Android Library 中的时候,就开始提示错误了,表示无法这样使用,下面就这个问题来进行一个简单的讲解,并提供一个快速解决的方法。
二、为什么会有这样的问题?
我们先来看看报错信息。
点击查看更多『more』。
可以看到错误的说明。这里明说了,无法在 Android Library 中,使用 switch 语句,来操作一个 IDs 的资源。
那么是什么导致出现这样的问题呢?
我们知道,switch 语句的 case 操作必须是一个常量。而在 App Module 中,IDs 本身在 R.java 中就是被定义为一个一个常量而存在的,那么在 Android Library 中,这一点是否会有变化呢?
先来看看 App 的 R.java。
再来看看 Android Library Module 中生成的 R.java 文件。
可以看到,确实是有不一样的,在 Android Library Module 中,生成的 R.java 文件中,所有的 IDs 都是 static 的,而非 static final 的。也就是说,它不再是一个常量了。
而官方其实也有资料来说明这个问题。
有兴趣的可以直接阅读原文,大致的意思是在 SDK Tools r14 开始,在 Library Module 中,会将 IDs 的资源,声明为 static 而非 static final 。
而这么设计的原因是,在多个 Module 组合的项目中,如果需要确保每个 Module 中的 IDs 资源的值在整个项目中都是唯一的话,就需要每次编译的时候都将所有的资源和相关的 Java 代码与主项目一起重新编译,为每个 IDs 的资源,都生成一个唯一的值,这样就会影响构建的效率。同时它也限制了发布 Android Library 就必须发布源码,从而限制了 Android Library 的使用范围。所以在 SDK Tools r14 开始,就将 Android Library 中的 IDs 标记为非 final 类型的。
三、如何快速替换 Switch 语句
而官方也提供了解决方案,就是使用 if-else 语句替换 switch-case 语句。如果我们是从零开始编写逻辑,直接使用 if-esle 来编写这种逻辑即可,但是我们是在 copy 一个现有的项目,那么问题就变成了,如何快速的将 switch-case 替换为 if-else 语句。
在 Android Studio 中,是提供了快捷键来一键替换的。如果没有修改过,在 Mac 中,快捷键是 command + return
,在 Windows 中,快捷键是 Alt + Enter
。
如果快捷键有变动,可以在 KeyMap 中,查找 Show Intention Actions ,查看被设置的快捷键。
而 Intention 实际上提供了非常多的快捷操作,这里只是命中了当前 switch 替换 if 的场景了而已,更多的快捷操作,可以在 Intentions 窗口中查看。
四、结语
本身这样的一件事情,根据 提示就解决了,但是作为开发者,不应该只是满足解决问题,应该从更深层次的来探讨问题的原因,为什么如此设计,如何快速的解决这个问题。